
typedef  volatile unsigned int * REG;

#define GPJ2CON		(*(volatile unsigned int *)0xe0200280)
#define GPJ2DAT		(*(volatile unsigned int *)0xe0200284)

//#define GPIO_MACRO
#define FIX_GPBOUT

#ifdef DEBUG
	REG a,b;
	#define _GPBCON (a)  
	#define _GPBDAT (b)
	#define GPBCON (*a)
	#define GPBDAT (*b)
#else
	#define GPBCON      (*(volatile unsigned int *)0xe0200040)
	#define GPBDAT      (*(volatile unsigned int *)0xe0200044)
	#define _GPBCON     	((volatile unsigned int *)0xe0200040)
	#define _GPBDAT     	((volatile unsigned int *)0xe0200044)
    #define __GPBCON        0xe0200040
    #define __GPBDAT        0xe0200044
#endif


#define GPH2CON		(*(volatile unsigned int *)0xE0200C40)
#define GPH2DAT		(*(volatile unsigned int *)0xE0200C44)

#define phy_wr(_phys, _val) ((_phys) = (_val))
#define phy_clear(_phys, _mask) ((_phys) &= ~(_mask))
#define phy_set(_phys, _mask) ((_phys) |= (_mask))

#define gpio_phy_set(_phy, _gpio, val) do {     \
    if ((val) & 0x1) {                      \
        phy_set((_phy), (1<<(_gpio)));      \
    } else {                                \
        phy_clear((_phy), (1<<(_gpio)));    \
    }   \
}while(0);


#define reg_rd(_phys) (*(REG)(_phys))
#define reg_wr(_phys, _val) ((*(REG)(_phys)) = (_val))

#if 1
#define reg_clear(_phys, _mask) ((*(REG)(_phys)) &= ~(_mask))
#define reg_set(_phys, _mask) ((*(REG)(_phys)) |= (_mask))
#else
#define reg_clear(_reg, _mask) reg_wr((_reg), (reg_rd(_reg) & ~(_mask) )) 
#define reg_set(_reg, _mask)  reg_wr((_reg), (reg_rd(_reg) | (_mask) )) 
#endif

#define reg_set_val(_reg, _bits, _gpio, _val) do { \
    reg_clear((_reg), (((1<<(_bits)) - 1) << ((_gpio) * (_bits)))); \
    reg_set( (_reg), ((_val) << ((_gpio) * (_bits))) ); \
    reg_rd( (_reg) ); \
} while(0);

#define GPIO_CON_BITS  4
#define GPIO_OUT_MODE 1

#define gpio_out(_reg, _gpio) reg_set_val((_reg), (GPIO_CON_BITS), (_gpio), (GPIO_OUT_MODE))

#define gpio_set(_reg, _gpio, val) do { 	\
	if ((val) & 0x1) {						\
		reg_set((_reg), (1<<(_gpio)));		\
	} else {								\
		reg_clear((_reg), (1<<(_gpio)));	\
	}	\
}while(0);


#ifdef DEBUG
#include <stdio.h>
void dump_hex(char *str, int val) {
	printf("%s=0x%x\n", str, val);
}

void dump_4bit(char *str, int val) {
    int i = 0;
    printf("%s=0x%08x	", str, val);
    for (i=7; i>=0; i--) {
        printf("%d",(val>>(i * 4)) & 0xf);
    }
    printf("\n");
}

void dump_bit(char *str, int val) {
	int i = 0;
	printf("%s=0x%08x	", str, val);
	for (i=31; i>=0; i--) {
		printf("%d",(val>>i) & 0x1);
	}
    printf("\n");
}
#else
#define dump_hex(str, val)
#define dump_4bit(str, val)
#define dump_bit(str, val)

#endif

void delay()
{
	volatile int i = 0x100000;
	while (i--);
}

typedef struct led {
	char type;
	int gpio;
	REG con;
	REG dat;
}LED;


int set_leds(LED leds[], int num, int on){
	int i = 0;
	char type = leds[i].type;
    int gpio = leds[i].gpio;
#ifdef FIX_GPBOUT
	GPBCON &= ~0xffff;
    GPBCON |= 0x1111;
#endif
	/* set output mode*/
        for(i=0; i<num; i++) {
			type = leds[i].type;
			gpio = leds[i].gpio;
           	if ( type = 'B') {
				#ifdef GPIO_MACRO
            	//gpio_out(_GPBCON, gpio);
				//gpio_set(_GPBDAT, gpio, on);
				
				gpio_phy_set(GPBDAT, gpio, on);
				#else
				//GPBCON &= ~(0xf << ( gpio * 4));
				//GPBCON |= (0x1 << (gpio * 4));
				if( on & 0x1) {
					GPBDAT |= (1<<(gpio));
				} else {
					GPBDAT &= ~(1<<(gpio));
				}
				#endif
	    	}             
			//dump_4bit("con", *(leds[i].con));
        }
	dump_bit("set_leds dat", *(leds[0].dat));
	return 0; 
}

int turn_on(LED *led) {
    int gpio = led->gpio;
    char type = led->type;
#ifdef FIX_GPBOUT
    GPBCON &= ~0xffff;
    GPBCON |= 0x1111;
#endif	
	if ( type = 'B') {
		#ifdef GPIO_MACRO
			//gpio_out(_GPBCON, gpio);
        	//gpio_set(_GPBDAT, gpio, 1);
			gpio_phy_set(GPBDAT, gpio, on);
		#else
			GPBDAT |= (1<<(gpio));
		#endif
    }
    dump_bit("trun on dat", *(led->dat));
}

int test2(void) {
	int num = 0;
	int i = 0;
#ifdef DEBUG
	int times = 3 * 4;
	volatile unsigned con = 0;
	volatile unsigned dat = 0;
	a = &con;
	b = &dat;
	LED leds[] = {
                {'B', 0, a, b},
                {'B', 1, a, b},
                {'B', 2, a, b},
                {'B', 3, a,	b}
                };
#else
	GPBCON &= ~0xffff;
    GPBCON |= 0x1111;
	LED leds[] = { 
		{'B', 0, _GPBCON, _GPBDAT},
		{'B', 2, _GPBCON, _GPBDAT},
		{'B', 1, _GPBCON, _GPBDAT},
		{'B', 3, _GPBCON, _GPBDAT}
		};
#endif	
	num = sizeof leds / sizeof (LED);
	set_leds(leds, num, 1);
	delay();
	set_leds(leds, num, 0);
	
	for(i=0; i<num; i++)
	{
#ifdef DEBUG
        if (times) {
            times -= 1;
        } else {
            break;
        }
#endif
		set_leds(leds, num, 0);
		turn_on(&leds[i]);
		delay();
		
		if (i == num - 1) i = -1;
	}
	return 0;
}

int test3(void){
	int i = 0;
	int on = 1;

	int leds[] ={0,2,1,3};
	int gpio = 0;
	int num = sizeof(leds) / sizeof(int);

#ifdef DEBUG
    int times = 3 * 4;
    volatile unsigned con = 0;
    volatile unsigned dat = 0;
    a = &con;
    b = &dat;
#endif

    GPBCON &= ~0xffff;
    GPBCON |= 0x1111;
    
	for(i=0; i<num; i++)
    {
		gpio = leds[i];
#ifdef DEBUG
        if (times) {
            times -= 1;
        } else {
            break;
        }
#endif
		if (on) {
        	GPBDAT |= (1 << gpio);
		} else {
			GPBDAT &= ~(1 << gpio);
		}
#ifdef DEBUG
		dump_bit("test3 on dat", GPBDAT);
#endif
        delay();

        if (i == (num - 1)) {
			i = -1;
			if (on) {
				on = 0;
			} else {
				on = 1;
			}
		}
    }
	return 0;
}
int test1(void){
	int i = 0;
	int trigle = 1;
	GPBCON &= ~0xffff;
    GPBCON |= 0x1111;
	
        for(i=0; i<4; i++)
        {                                   
                GPBDAT &= ~0xff;
                GPBDAT |= trigle << i;
                delay();
        }
	return 0;
}

int main(void) {

#ifndef DEBUG
	test1();
#endif
	test3();
	test2();
	return 0;
}


